//
//  ScanBarcodeViewController.swift
//  GreenDeal
//
//  Created by Moennig Q on 16/11/2022.
//

import UIKit
import CoreLocation
import IQKeyboardManagerSwift
protocol PanelOrInverterRefreshDelegate {
    func refreshList()
    func refreshListBeforeUploading()
}
class ScanBarcodeViewController: BaseViewController {
    var scanningType: ScanningType = .panel
    var scanAddMethodMode: ScanAddMethodMode = .auto
    var customView: ScannerCommonUIView!
    var currentLocation: CLLocation?
    var model : PVDDetailModel!
    var barcodeCnt: Int = 0
    var scannerView: ScannerViewProtocal!
    var invertedBarcodeEnabledFlag: Bool = false//默认不开启反色条码
    var fuzzyScanEnabledFlag: Bool = false//默认不开启模糊扫描
    var scanningColor: UIColor = UIColor(hexStr: "#54EE07")
    //
    //存储手动增加时，扫描识别到的code结果
    var manuallyResult: ScanningResult = ScanningResult()
    //是否已经检查了inverter的数量，每次启动inverter扫描增加数据时，都要提示
    var haveCheckedInverterCntFlag: Bool = false
    /// MARK: - 生命周期方法
    override open func viewDidLoad() {
        super.viewDidLoad()
        self.model = JobDetailModelHelper.shared.jobDetailModel
        //获取当前经纬度信息
        //最后
        self.requestLocationInfo()
        self.setUpScanner()
        self.initUI()
        
    }
    func setUpScanner(){
        //初始化Dynamsoft Scanner
        if APPConfig.ScannerLicenseValidFlag {
            scannerView = DynamsoftScannerView()
        }else{//初始化原生scanner
            scannerView = NativeScannerView()
        }
        scannerView.frame = self.view.frame
        self.view.addSubview(scannerView)
        scannerView.scanResultClosure = {[weak self] (result) in
            guard let strongSelf = self else { return }
            if strongSelf.scannerView.scanAddMethodMode == .auto{
                strongSelf.dealBarcodeResult(result)
            }else{
                if strongSelf.checkIfInvalid(result.realBarcode){//检查invalid
                    //此处不能把result直接赋值给strongSelf.manuallyResult，因为拍照时后可能会返回到这里，赋值的imageData会被覆盖掉清空，导致增加失败
                    strongSelf.manuallyResult.barcode = result.realBarcode
                    strongSelf.manuallyResult.type = result.type
                    strongSelf.customView.setBarcodeText(result.realBarcode)
                }
            }
        }
        //takephoto的回调
        scannerView.takePhotoResultClosure = {[weak self] (imageData) in
            guard let strongSelf = self else { return  }
            strongSelf.scannerView.stopScanning()
            strongSelf.manuallyResult.imageData = imageData
            strongSelf.customView.enableCodeTextField()
            if strongSelf.customView.nativeScanFlag == false{//三方扫描才需要剪切图片
                strongSelf.customView.showTakePhotoImage(strongSelf.scannerView.scanMode, imageData: imageData)
            }
        }
        
        scannerView.scanAddMethodMode = self.scanAddMethodMode
        //MARK: - 检查是否有需要自动开启inverter code 的panel brand
        if self.scanningType == .panel {
            //1.inverted code  setting
            if APPConfig.ScannerPanelBrandOrModelForInvertedCode != ""{
                for panelModel in self.model.system_detail.panels {
                    if APPConfig.ScannerPanelBrandOrModelForInvertedCode.contains(panelModel.brand + ";") || APPConfig.ScannerPanelBrandOrModelForInvertedCode.contains(panelModel.model + ";") {
                        self.invertedBarcodeEnabledFlag = true
                        break
                    }
                }
            }
            //2.fuzzy code setting
            if APPConfig.ScannerPanelBrandOrModelForFuzzyCode != ""{
                for panelModel in self.model.system_detail.panels {
                    if APPConfig.ScannerPanelBrandOrModelForFuzzyCode.contains(panelModel.brand + ";") || APPConfig.ScannerPanelBrandOrModelForFuzzyCode.contains(panelModel.model + ";"){
                        self.fuzzyScanEnabledFlag = true
                        break
                    }
                }
            }
        }
        scannerView.launchScanner(enableInvetedFlag: self.invertedBarcodeEnabledFlag,enableFuzzyFlag: self.fuzzyScanEnabledFlag)
    }
    func initUI(){
        self.customView = ScannerCommonUIView(self.scanningType,nativeScanFlag: !APPConfig.ScannerLicenseValidFlag)
        self.view.addSubview(self.customView)
        self.customView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        //1.是否有设备
        let deviceAvailable = self.scannerView.checkIfHaveAvailableDevice()
        self.customView.showUnavailableDeviceMsg(deviceAvailable)
        
        //2.共用操作按钮
        self.customView.switchTorchBtnClickClosure = {[weak self] in
            guard let strongSelf = self else { return  }
            strongSelf.switchTorch()
        }
        self.customView.switchScanModeBtnClickClosure = {[weak self] in
            guard let strongSelf = self else { return  }
            strongSelf.switchScanMode()
        }
        self.customView.cancelBtnClickClosure = {[weak self] in
            guard let strongSelf = self else { return  }
            strongSelf.dissmissVC()
        }
        self.customView.switchAddMethodBtnClickClosure = {[weak self] in
            guard let strongSelf = self else { return  }
            strongSelf.switchScanAddMethodMode()
        }
        self.customView.takePhotoBtnClickClosure = {[weak self] in
            guard let strongSelf = self else { return  }
            strongSelf.scannerView.takePhoto()
        }
        //manually编辑barcode后点击键盘上的Done的回调
        self.customView.manuallyConfirmClosure = {[weak self] (editedBarcode) in
            guard let strongSelf = self else { return  }
            strongSelf.customView.clearCodeTextField()
            strongSelf.customView.clearTakePhotoImage()
            if editedBarcode == ""{
                strongSelf.scannerView.startScanning()
            }else {
                strongSelf.manuallyResult.barcode = editedBarcode
                strongSelf.dealBarcodeResult(strongSelf.manuallyResult)
            }
            //清空上次的识别数据
            strongSelf.scannerView.clearPreResultForManually()
            strongSelf.manuallyResult = ScanningResult()
            
        }
        //3.设置中的两种选择
        self.customView.settingView.fuzzySwitchBtnClosure = {[weak self] in
            guard let strongSelf = self else { return }
            strongSelf.fuzzyScanEnabledFlag = !strongSelf.fuzzyScanEnabledFlag
            strongSelf.customView.settingView.setFuzzySwitchBtn(strongSelf.fuzzyScanEnabledFlag)
            strongSelf.scannerView.switchFuzzyScanSetting(strongSelf.fuzzyScanEnabledFlag)
            
        }
        self.customView.settingView.invertedSwitchBtnClosure = {[weak self] in
            guard let strongSelf = self else { return }
            strongSelf.invertedBarcodeEnabledFlag = !strongSelf.invertedBarcodeEnabledFlag
            strongSelf.customView.settingView.setInvertedSwitchBtn(strongSelf.invertedBarcodeEnabledFlag)
            strongSelf.scannerView.switchInverterSetting(strongSelf.invertedBarcodeEnabledFlag)
        }
        //4.tableview中的操作
        self.customView.deleteBarcodeClosure =  {[weak self] (deletedBarcode) in
            guard let strongSelf = self else { return }
            strongSelf.deleteScannedBarcode(deletedBarcode)
        }
        //MARK: - 操作UI 初始化设置
        self.customView.switchScanAddMethodMode(self.scannerView.scanAddMethodMode)
        self.customView.switchScanMode(scannerView.scanMode)
        //setUpScanner()中初始化inverter和fuzzy的初始值
        self.customView.settingView.setInvertedSwitchBtn(self.invertedBarcodeEnabledFlag)
        self.customView.settingView.setFuzzySwitchBtn(self.fuzzyScanEnabledFlag)
        //
        if let m = self.model {
            if self.scanningType == .panel{
                barcodeCnt = m.pvd_serial_numbers.count
                self.customView.setBarcodeCountText(barcodeCnt, planCntStr: "\(m.system_detail.panel_plant_count)")
            }else{
                barcodeCnt = m.pvd_inverter_serial_numbers.count
                self.customView.setBarcodeCountText(barcodeCnt, planCntStr: "\(m.system_detail.inverter_plant_count)")
            }
        }
    }
    // MARK: - 点击事件
    func switchTorch() {
        let onFlag = scannerView.switchTorchMode()
        self.customView.switchTorchBtn(onFlag)
    }
    // MARK: - 切换手工增加还是扫描增加
    func switchScanAddMethodMode(){
        self.scannerView.scanAddMethodMode = (self.scannerView.scanAddMethodMode == .auto ? .manually : .auto)
        customView.switchScanAddMethodMode(self.scannerView.scanAddMethodMode)
        //切换增加模式的时候：可能正在编辑手工添加的代码
        if !self.scannerView.isScanning{//如果没有在扫描就再次开启
            scannerView.startScanning()
        }
    }
    // MARK: - 切换扫码类型
    func switchScanMode(){
        let newScanMode: ScanMode = (scannerView.scanMode == .oneD ? .qrCODE : .oneD)
        scannerView.switchScanMode(newScanMode)
        customView.switchScanMode(newScanMode)
    }
    // MARK: - 关闭扫描界面
    func dissmissVC() {
        self.dismiss(animated: true) {
            if APPConfig.ScannerLicenseValidFlag {
                ScannerManager.shared.pauseScanner()
            }
        }
    }
    //MARK: - 增加方式是Auto：处理返回的扫码结果
    func dealBarcodeResult(_ result: ScanningResult){
        //0.处理barcode
        let barcode = self.dealRealBarcode(result)
        //1.检查code是否能invalid，是否重复
        if self.checkIfCanBeAdded(barcode) == false {
            if self.scannerView.scanAddMethodMode == .manually{//手工增加的需要重新开启
                self.scannerView.startScanning()
            }
            return
        }
        //2.增加数据
        var realResult = result
        realResult.barcode = barcode
        self.addBarcode(realResult)
        //3.增加完数据，检验inverter数量是否增加的正确，不正确给与提示
        if let checkMsg = self.checkInverterCnt() {//不正确
            self.haveCheckedInverterCntFlag = true
            self.scannerView.stopScanning()
            Tool().showAlertViewWithOneBtn(title: "Panel or Inverter", message: checkMsg) {
                self.scannerView.startScanning()
            }
        }else{//正确
            if self.scannerView.scanAddMethodMode == .manually{//手工增加的需要重新开启
                self.scannerView.startScanning()
            }
        }
    }
    private func checkInverterCnt()->String?{
        var msg: String?
        //inverter时，已扫描判断数量是否大于panel已经扫描的数量，如果大于给与提示，且每次启动扫描只提示一次
        if let m = self.model, self.scanningType == .inverter && self.haveCheckedInverterCntFlag == false {
            let scannedPanelNumbersCnt = m.pvd_serial_numbers.count
            if self.barcodeCnt > scannedPanelNumbersCnt && scannedPanelNumbersCnt > 0{
                msg = "The number of inverter is bigger than panel's? Please make sure you are not uploading Panel serial numbers here."
            }else if self.barcodeCnt > 1 && scannedPanelNumbersCnt == 0{//inverter实际数量大于计划数量
                msg = "Please make sure you are not uploading Panel serial numbers here."
            }
        }
        return msg
    }
    //MARK: - 将返回的code去掉空格，如果是datamatrix去掉\t
    private func dealRealBarcode(_ result: ScanningResult)->String{
        var barcode = result.realBarcode
        //检查code是否是 DataMatrix
        if  result.type.uppercased().contains("DATAMATRIX") {
            let seperator = "\t"
            if barcode.contains(seperator) {
                let result = barcode.components(separatedBy: seperator)
                if result.count > 0 {
                    barcode = result[0]
                }
            }
        }
        return barcode
    }
    private func checkIfInvalid(_ barcode: String)->Bool{
        //检查code是否有效
        if barcode.lowercased().contains("http") {
            self.customView.showInvalidMsg("Invalid")
            return false
        }
        return true
    }
    private func checkIfDuplicated(_ barcode: String)->Bool{
        //检查code是否在已扫描界面列表中重复
        let (existScannedFlag, scannedIndex) = self.checkIfScannedNumberExist(barcode)
        if existScannedFlag {
            self.customView.showDuplicatedEffect(barcode, scannedIndex: scannedIndex)
            return false
        }
        //检查panel的重复
        var existFlag: Bool = false
        if scanningType == .panel {
            existFlag = self.checkIfPanelNumberExist(barcode)
        }else{//检查inverter的重复
            existFlag = self.checkIfInverterNumberExist(barcode)
        }
        if existFlag {//已存在,提示重复信息
            self.customView.showDuplicatedEffect(barcode, scannedIndex: scannedIndex)
            return false
        }
        return true
    }
    //检查是否可以增加，code中包含http，或重复都不能增加
    private func checkIfCanBeAdded(_ barcode: String)->Bool{
        if !self.checkIfInvalid(barcode){//无效
            return false
        }
        if !self.checkIfDuplicated(barcode){//重复
            return false
        }
        return true
    }
    private func checkIfBarcodeInvalid(_ barcode: String)->Bool{
        var validFlag: Bool = true
        //检查是否有相同长度，或符合正则表达式
        if self.scanningType == .panel {//panel
            if Tool().isValidPanelNumber(str: barcode) {//通过正则表达式校验，只包含字母数字和-,且长度大于8位
//                if self.barcodeCnt > 0 {//扫描的第二个(包括两个)以上的号码
//                    if !self.checkPanelNumberLength(barcode){//没有找到相同长度的code
//                        validFlag = false
//                    }
//                }
            }else{//不符合正则表达式：包含有特殊字符或者长度小于等于8位
                validFlag = false
            }
        }else{
            if Tool().isValidInverterNumber(str: barcode) {//只包含字母数字和-,且长度大于8位
//                if self.barcodeCnt > 0 {//扫描的第二个(包括两个)以上的号码
//                    if !self.checkInverterNumberLength(barcode){//没有找到相同长度的code
//                        validFlag = false
//                    }
//                }
            }else{//包含有特殊字符或者长度小于等于8位
                validFlag = false
            }
        }
        
        
        return validFlag
    }
    //MARK: - 增加barcode数据处理
    func addBarcode(_ result: ScanningResult){
        guard let imageData = result.imageData else{
            return
        }
        guard let image = UIImage(data: imageData) else{
            return
        }
        MediaUtil().playSound("beep.wav")
        //检查是否有相同长度，或符合正则表达式
        let validFlag = self.checkIfBarcodeInvalid(result.realBarcode)//要过滤掉逗号，因为spv的code验证时不能有逗号
        //增加barcode，并刷新tableview
        let bModel = ScannedBarcodeModel(barcode: result.realBarcode, validFlag: validFlag)
        self.customView.scannedBarcodeList.insert(bModel, at: 0)
        self.customView.tableView.reloadData()
        self.customView.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableView.ScrollPosition.top, animated: true)
        
        //resize image to 30K
        let resizeImageData = MediaUtil().resetSizeOfImageData(source_image: image,maxSize: 100)

        //barcode image
        var barcodeImagePath  = ""
        let fileName = DateUtil().getCurrentDatetimeTamp()
        if self.scanningType == .panel {
            barcodeImagePath = FileUtil().getPanelNumberImagePath(fileName)
        }else{
            barcodeImagePath = FileUtil().getInverterNumberImagePath(fileName)
        }
        

        do {
            try resizeImageData.write(to: URL(fileURLWithPath: barcodeImagePath), options: [.atomic])
        }catch{
            NSLog("Saving barcode image to local failed")
        }
        let panelModel = PanelNumberImageDBModel()
        panelModel.pvd_id = self.model!.id
        panelModel.original_code = result.realBarcode
        panelModel.code = result.realBarcode
        panelModel.image = barcodeImagePath
        panelModel.validFlag = validFlag
        panelModel.latitude = self.currentLocation?.coordinate.latitude
        panelModel.longitude = self.currentLocation?.coordinate.longitude
        panelModel.auto_scan = (self.scannerView.scanAddMethodMode == .auto ? 1 : 0)
        if self.scannerView.scanAddMethodMode == .auto {
            panelModel.scan_type = (APPConfig.ScannerLicenseValidFlag ? 1 : 2)//1.Dynamsoft扫描，2.原生扫描
        }else{
            panelModel.scan_type = 0//手动增加时，默认为0
        }
        
        panelModel.confidence = result.confidence
        panelModel.record_at = DateUtil().getCurrentDatetime()
        panelModel.barcode_type = result.type
        panelModel.scan_timespan = result.scanTime
        panelModel.operType = DataOperType.Add.rawValue
        //设置数量
        self.barcodeCnt +=  1
        //增加到本地数据库，然后上传刷新
        if self.scanningType == .panel {
            self.customView.setBarcodeCountText(barcodeCnt, planCntStr: "\(self.model.system_detail.panel_plant_count)")
            //0.插入数据库
            DBManager.shared.insertSerialNumberData(model: panelModel, tableName: panelnumber_table_name)
            //1.增加到当前list中，触发didset，自动刷新数据
            JobDetailModelHelper.shared.jobDetailModel.pvd_serial_numbers.insert(panelModel, at: 0)
            JobDetailModelHelper.shared.jobDetailModel.broadCastPanelData()
            //3.上传
            UploadManager.shared.uploadOnePanelNumber(panelModel){  [weak self] (successFlag, panelM) in
                if let retModel =  panelM, successFlag{
                    self?.refreshScannedBarcodeList(retModel.code)
                }
            }
        }else{
            self.customView.setBarcodeCountText(barcodeCnt, planCntStr: "\(self.model.system_detail.inverter_plant_count)")
            //2.插入数据库
            DBManager.shared.insertSerialNumberData(model: panelModel, tableName: inverternumber_table_name)
            //1.增加到当前list中
            JobDetailModelHelper.shared.jobDetailModel.pvd_inverter_serial_numbers.insert(panelModel, at: 0)
            JobDetailModelHelper.shared.jobDetailModel.broadCastInverterData()
            //3.上传
            UploadManager.shared.uploadOneInverterNumber(panelModel){ [weak self] (successFlag, inverterModel) in
                if let retModel =  inverterModel, successFlag{
                    self?.refreshScannedBarcodeList(retModel.code)
                }
            }
        }
    }
    // MARK: - 上传成功后刷新是否上传成功的标记
    @objc fileprivate func refreshScannedBarcodeList(_ uploadedCode: String){
        if let index = self.customView.scannedBarcodeList.firstIndex(where: { $0.barcode == uploadedCode}){
            self.customView.scannedBarcodeList[index].uploadedFlag = true
            self.customView.tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: UITableView.RowAnimation.none)
        }
    }
    //MARK: - 检查扫描界面上已经scanned的list中是否重复
    fileprivate func checkIfScannedNumberExist(_ newBarcode: String)->(Bool, Int?){
        var scannedIndex: Int? = nil
        //1.最后一道保险：
        if let duplicatedIndex = self.customView.scannedBarcodeList.firstIndex(where: { $0.barcode == newBarcode}) {
            scannedIndex = duplicatedIndex
            return (true,scannedIndex)
        }
        return (false,scannedIndex)
    }
    fileprivate func checkIfPanelNumberExist(_ newBarcode: String)->Bool{
        
        if let _ = self.model.pvd_serial_numbers.firstIndex(where: {($0.code == newBarcode)}){
            return true
        }

        return false

    }
    fileprivate func checkIfInverterNumberExist(_ newBarcode: String)->Bool{
        if let _ = self.model.pvd_inverter_serial_numbers.firstIndex(where: {($0.code == newBarcode)}){
            return true
        }
        return false
    }
    //MARK: - 删除扫描列表中的数据
    private func deleteScannedBarcode(_ code: String){
        //1.先检查是否在上传中
        let tableName = (self.scanningType == .panel ? panelnumber_table_name : inverternumber_table_name)
        let uploadingFlag: Bool = DBManager.shared.checkLocalBarcodeUploadingByCode(tableName: tableName, code: code)
        //正在上传中的barcode，不做处理；已经上传或本地未上传的才能删除
        if uploadingFlag {
            return
        }
        Tool().showAlertViewWithTwoBtns(title: code,message: "Are you sure you want to delete this serial?", yesClosure:  {
            //删除列表里边的数据，病数显
            self.customView.deleteOneRow(code)
            //set 数量
            self.barcodeCnt -= 1
            //
            if self.scanningType == .panel {
                self.customView.setBarcodeCountText(self.barcodeCnt, planCntStr: "\(self.model.system_detail.panel_plant_count)")
                //已经上传
                if let index = self.model?.pvd_serial_numbers.firstIndex(where: {$0.code == code}){
                    let panelModel = self.model.pvd_serial_numbers[index]
                    panelModel.pvd_id = self.model.id
                    panelModel.operType = DataOperType.Del.rawValue
                    //增加到删除的列表中
                    JobDetailModelHelper.shared.jobDetailModel.localDeletedSerialNumbers.append(panelModel)
                    //将删除记录先存在本地库中，防止没有删除成功
                    DBManager.shared.delSerialNumberData(model: panelModel,tableName: panelnumber_table_name)
                    //有网络才能请求删除删除
                    if Connectivity.isConnectedToInternet {
                        ModelViewUtil.shared.showLoadingView("Deleting...")
                        UploadManager.shared.uploadOnePanelNumber(panelModel) { (successFlag, code) in
                            ModelViewUtil.shared.hideLoadingView()
                        }
                    }
                }else{
                    DBManager.shared.deleteLocalBarcodeByCode(tableName: panelnumber_table_name, code: code)
                }
            }else {//inverter
                self.customView.setBarcodeCountText(self.barcodeCnt, planCntStr: "\(self.model.system_detail.inverter_plant_count)")
                //已经上传
                if let index = self.model?.pvd_inverter_serial_numbers.firstIndex(where: {$0.code == code}){
                    let panelModel = self.model.pvd_inverter_serial_numbers[index]
                    panelModel.pvd_id = self.model.id
                    panelModel.operType = DataOperType.Del.rawValue
                    //增加到删除的列表中
                    JobDetailModelHelper.shared.jobDetailModel.localDeletedInverterNumbers.append(panelModel)
                    DBManager.shared.delSerialNumberData(model: panelModel,tableName: inverternumber_table_name)
                    //有网络才能请求删除删除
                    if Connectivity.isConnectedToInternet {
                        ModelViewUtil.shared.showLoadingView("Deleting...")
                        UploadManager.shared.uploadOnePanelNumber(panelModel) { (successFlag, code) in
                            ModelViewUtil.shared.hideLoadingView()
                        }
                    }
                }else{
                    DBManager.shared.deleteLocalBarcodeByCode(tableName: inverternumber_table_name, code: code)
                }
            }
        })
    }
    //MARK: - 请求定位信息
    func requestLocationInfo(){
        LocationManager.shared.subscription(.single).fetchWithCompletion {[weak self](location, error) in
            guard let strongSelf = self else { return  }
            if location != nil {
                strongSelf.currentLocation = Tool().convertCoordinate(location!)
            }
        }
    }
    override open func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        //hide navigation bar
        self.navigationController?.navigationBar.isHidden = true
        //手动增加时，点击键盘外IQKeyboardManager会关闭键盘，和需求冲突，这里IQKeyboardManager设置为失效，点击键盘外不关闭键盘
        IQKeyboardManager.shared.shouldResignOnTouchOutside = false//键盘弹出时，点击键盘外背景，键盘不收回
    }
    override open func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        IQKeyboardManager.shared.shouldResignOnTouchOutside = true//键盘弹出时，点击键盘外背景，键盘不收回
        self.scannerView.stopScanning()
        //获取license key,panel number的正则表达式
        Tool().getScanLicenseAndRegularExpression()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        DebugLog("\(self) didReceiveMemoryWarning")
    }
}
